
package com.jf.cloud.delivery.service.impl;

import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.jf.cloud.api.delivery.dto.StationSalesDTO;
import com.jf.cloud.api.delivery.vo.StationVO;
import com.jf.cloud.api.feign.SearchOrderFeignClient;
import com.jf.cloud.api.order.constant.OrderStatus;
import com.jf.cloud.common.database.dto.PageDTO;
import com.jf.cloud.common.database.util.PageUtil;
import com.jf.cloud.common.database.vo.PageVO;
import com.jf.cloud.common.order.dto.OrderSearchDTO;
import com.jf.cloud.common.order.vo.EsOrderVO;
import com.jf.cloud.common.order.vo.OrderVirtualInfoVO;
import com.jf.cloud.common.util.Arith;
import com.jf.cloud.common.util.Json;
import com.jf.cloud.delivery.bo.StationOrderBO;
import com.jf.cloud.delivery.dto.StationDTO;
import com.jf.cloud.delivery.mapper.StationMapper;
import com.jf.cloud.delivery.model.Station;
import com.jf.cloud.delivery.service.StationService;
import com.jf.cloud.delivery.vo.StationDetailVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 自提点信息
 *
 * @author zz
 * @date 2020-12-07 15:10:01
 */
@Service
public class StationServiceImpl implements StationService {

    @Autowired
    private StationMapper stationMapper;
    @Autowired
    private SearchOrderFeignClient searchOrderFeignClient;

    private final int TEN = 10;
    private final int TWELVE = 12;
    private final int EIGHTEEN = 18;
    private final int THIRTY = 30;

    @Override
    public PageVO<StationVO> page(PageDTO pageDTO) {
        return PageUtil.doPage(pageDTO, () -> stationMapper.list());
    }

    @Override
    public PageVO<StationVO> pageStation(PageDTO pageDTO, StationDTO stationDTO) {
        return PageUtil.doPage(pageDTO, () -> stationMapper.listStation(stationDTO));
    }

    @Override
    public StationVO getByStationId(Long stationId) {
        return stationMapper.getByStationId(stationId);
    }

    @Override
    public void save(Station station) {
        stationMapper.save(station);
    }

    @Override
    public void update(Station station) {
        stationMapper.update(station);
    }

    @Override
    public void deleteById(Long stationId) {
        stationMapper.deleteById(stationId);
    }

    @Override
    public void logicDeleteById(Long stationId) {
        stationMapper.logicDeleteById(stationId);
    }

    @Override
    public List<StationSalesDTO> getStationSalesRecord(Long shopId, Long stationId) {
        // es订单检索数据准备
        OrderSearchDTO orderSearchDTO = new OrderSearchDTO();
        orderSearchDTO.setStationId(stationId);
        orderSearchDTO.setGtePayTime(true);
        orderSearchDTO.setStatusList(Arrays.asList(
                OrderStatus.PAYED.value(),
                OrderStatus.CONSIGNMENT.value(),
                OrderStatus.SUCCESS.value(),
                OrderStatus.WAIT_GROUP.value())
        );
        Date day = DateUtil.beginOfDay(new Date());
        Date month = DateUtil.beginOfMonth(day);
        // 查询"当月"自提门店订单信息
        orderSearchDTO.setPayTime(month);
        List<EsOrderVO> esOrders = searchOrderFeignClient.listEsOrder(orderSearchDTO).getData();
        List<StationOrderBO> monthOrders = this.esOrderToStationOrder(esOrders, stationId);
        // 通过数据过滤，获取“当日”自提门店订单信息
        List<StationOrderBO> dayOrders = new ArrayList<>(16);
        if (!CollectionUtils.isEmpty(monthOrders)) {
            monthOrders.sort((o1, o2) -> o2.getPayTime().compareTo(o1.getPayTime()));
            for (StationOrderBO order : monthOrders) {
                if (order.getPayTime().compareTo(day) < 0) {
                    break;
                }
                dayOrders.add(order);
            }
        }
        // 数据统计
        StationSalesDTO daySalesDTO = this.calStationSales(dayOrders);
        daySalesDTO.setSalesType(1);
        StationSalesDTO monthSalesDTO = this.calStationSales(monthOrders);
        monthSalesDTO.setSalesType(2);
        return Arrays.asList(daySalesDTO, monthSalesDTO);
    }

    /**
     * es订单转成自提门店订单
     * @return
     */
    private List<StationOrderBO> esOrderToStationOrder(List<EsOrderVO> esOrders, Long stationId) {
        List<StationOrderBO> stationOrders = new ArrayList<>();
        StationOrderBO stationOrder;
        long prodPrice;
        // 遍历转换成门店订单数据
        for (EsOrderVO esOrder : esOrders) {
            stationOrder = new StationOrderBO();
            stationOrder.setUserId(esOrder.getUserId());
            stationOrder.setPayTime(esOrder.getPayTime());
            stationOrder.setAmount(0L);
            if (CollectionUtils.isEmpty(esOrder.getOrderVirtualInfoList())) {
                // 门店自提订单 [收益 = 订单实际金额 + 平台优惠金额]
                stationOrder.setAmount(esOrder.getActualTotal() + esOrder.getPlatformAmount());
            } else {
                // 虚拟核销订单 [核销单次收益 = (订单实际金额+平台优惠金额) / 订单商品数量]
                prodPrice = (long) Arith.div(Arith.add(esOrder.getActualTotal(), esOrder.getPlatformAmount()), esOrder.getAllCount(), 0);
                for (OrderVirtualInfoVO orderVirtualInfo : esOrder.getOrderVirtualInfoList()) {
                    if (Objects.equals(orderVirtualInfo.getStationId(), stationId)) {
                        stationOrder.setAmount(stationOrder.getAmount() + prodPrice);
                    }
                }
            }
            stationOrders.add(stationOrder);
        }
        return stationOrders;
    }

    /**
     * 统计数据
     *
     * @param orders
     * @return
     */
    private StationSalesDTO calStationSales(List<StationOrderBO> orders) {
        // TODO：暂只有门店订单数据，无核销数据，待订单改造
        StationSalesDTO stationSalesDTO = new StationSalesDTO();
        Set<Long> userIds = new HashSet<>();
        double payAmount = 0.0;
        double customerUnitPrice = 0.0;
        int orderNum = 0;
        if (!CollectionUtils.isEmpty(orders)) {
            orderNum += orders.size();
            for (StationOrderBO  order : orders) {
                userIds.add(order.getUserId());
                payAmount = Arith.add(payAmount, order.getAmount());
            }
            customerUnitPrice = Arith.div(payAmount, userIds.size(), 2);
        }
        // 赋值
        stationSalesDTO.setPayAmount(payAmount);
        stationSalesDTO.setPayOrderNumber(orderNum);
        stationSalesDTO.setUserNum(userIds.size());
        stationSalesDTO.setCustomerUnitPrice(customerUnitPrice);
        return stationSalesDTO;
    }

    @Override
    public PageVO<StationDetailVO> getStationList(Double lat, Double lng, String stationName, Long shopId, Long userId, PageDTO page) {
        PageVO<StationDetailVO> stationPage = PageUtil.doPage(page, () -> stationMapper.getStationList(page, lat, lng, stationName, shopId, null));
        List<StationDetailVO> stationList = stationPage.getList();
        for (StationDetailVO stationParam : stationList) {
            double distance = stationParam.getDistance();
            stationParam.setDistance(distance);
            String timeDate = stationParam.getTimeInfo();
            StationDetailVO.TimeInfoModeVO timeInfoModeVO = Json.parseObject(timeDate, StationDetailVO.TimeInfoModeVO.class);
//            List<TimeVO> TimeVOs = new ArrayList<>();
            Long[] shopTime = timeInfoModeVO.getShopTime();
//            int startHour = DateUtil.hour(new Date(shopTime[0]),true);
//            int endHour = DateUtil.hour(new Date(shopTime[1]),true);
            String startTime = DateUtil.format(new Date(shopTime[0]), "HH:mm");
            String endTime = DateUtil.format(new Date(shopTime[1]), "HH:mm");
            // 2023.02.28 移除提货时间间隔
//            List<String> hourTimes = Lists.newArrayList();
//            Date startStationTime = DateUtil.offsetDay(new Date(), Integer.valueOf(timeInfoModeVO.getStationStartTime()));
//            Date endStationTime = DateUtil.offsetDay(startStationTime,Integer.valueOf(timeInfoModeVO.getStationEndTime()));
//            String currentTime = DateUtil.format(new Date(),"HH:mm");
//            int currentHour = DateUtil.hour(startStationTime,true);
//            int currentMinute = DateUtil.minute(startStationTime);
//            //如果营业时间点大于当前时间点或提货日期不是今天，当前时间改为营业时间
//            try{
//                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//                long startDay = sdf.parse(sdf.format(startStationTime)).getTime();
//                long currentDay = sdf.parse(sdf.format(new Date())).getTime();
//                if(startHour > currentHour || startDay > currentDay ) {
//                    currentHour = startHour;
//                    currentMinute = DateUtil.minute(new Date(shopTime[0]));
//                }else if(startHour == currentHour){
//                    //如果相等，比较分钟
//                    if(DateUtil.minute(new Date(shopTime[0])) > currentMinute){
//                        currentMinute = DateUtil.minute(new Date(shopTime[0]));
//                    }
//                }
//            }catch (ParseException e){
//                e.printStackTrace();
//            }
//            if (Integer.valueOf(timeInfoModeVO.getStationStartTime()).equals(0) && endHour < currentHour){
//                startStationTime = DateUtil.offsetDay(startStationTime, 1);
//            }else {
//                if (timeInfoModeVO.getInterval().equals(2) && Integer.valueOf(timeInfoModeVO.getStationStartTime()).equals(0) && endHour > currentHour){
//                    hourTimes = getBusinessByNoon(currentHour, endHour, currentTime, endTime);
//                    TimeVOs.add(new TimeVO(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
//                    startStationTime = DateUtil.offsetDay(startStationTime,1);
//                }else if (timeInfoModeVO.getInterval().equals(3)){
//                    hourTimes = getBusinessByHour(currentHour, endHour, currentMinute, DateUtil.minute(new Date(shopTime[1])));
//                    TimeVOs.add(new TimeVO(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
//                    startStationTime = DateUtil.offsetDay(startStationTime,1);
//                }else if (timeInfoModeVO.getInterval().equals(4)){
//                    hourTimes = getBusinessByHalfHour(currentHour, endHour, currentMinute, DateUtil.minute(new Date(shopTime[1])));
//                    TimeVOs.add(new TimeVO(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
//                    startStationTime = DateUtil.offsetDay(startStationTime,1);
//                }
//            }
//            while (startStationTime.getTime() <= endStationTime.getTime()){
//                if (timeInfoModeVO.getInterval().equals(1)){
//                    List<String> hourTimeList = Lists.newArrayList();
//                    //hourTimeList.add(startHour + ":00-" + endHour + ":00");
//                    hourTimeList.add(startTime +"-" + endTime);
//                    TimeVOs.add(new TimeVO(DateUtil.format(startStationTime,"MM-dd"),hourTimeList));
//                }else if (timeInfoModeVO.getInterval().equals(2)){
//                    hourTimes = getBusinessByNoon(startHour, endHour, startTime, endTime);
//                    TimeVOs.add(new TimeVO(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
//                }else if (timeInfoModeVO.getInterval().equals(3)){
//                    hourTimes = getBusinessByHour(startHour, endHour, DateUtil.minute(new Date(shopTime[0])), DateUtil.minute(new Date(shopTime[1])));
//                    TimeVOs.add(new TimeVO(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
//                }else if (timeInfoModeVO.getInterval().equals(4)){
//                    hourTimes = getBusinessByHalfHour(startHour, endHour, DateUtil.minute(new Date(shopTime[0])), DateUtil.minute(new Date(shopTime[1])));
//                    TimeVOs.add(new TimeVO(DateUtil.format(startStationTime,"MM-dd"),hourTimes));
//                }
//                startStationTime = DateUtil.offsetDay(startStationTime,1);
//            }
//            stationParam.setTimeVOs(TimeVOs);
            stationParam.setBusiness(startTime + "-" + endTime);
        }
        return stationPage;
    }

    /**
     * 获取上中下午取货时间列表
     *
     * @param startHour 开始时间（小时）
     * @param endHour   结束时间（小时）
     * @param startTime 营业开始时间
     * @param endTime   营业结束时间
     * @return
     */
    private List<String> getBusinessByNoon(int startHour, int endHour, String startTime, String endTime) {
        String morning = "早上";
        String noon = "下午";
        String night = "晚上";
        List<String> hourTime = Lists.newArrayList();
        String secondSuf = "00";
        if (startHour < TWELVE) {
            if (endHour > EIGHTEEN) {
                hourTime.add(morning + "(" + startTime + "-12:00)");
                hourTime.add(noon + "(12:00-18:00)");
                hourTime.add(night + "(18:00-" + endTime + ")");
            } else if (endHour == EIGHTEEN) {
                hourTime.add(morning + "(" + startTime + "-12:00)");
                hourTime.add(noon + "(12:00-18:00)");
                String minute = endTime.split(":")[1];
                if(!Objects.equals(minute,secondSuf)){
                    hourTime.add(night + "(18:00-" + endTime + ")");
                }
            } else if (endHour > TWELVE) {
                hourTime.add(morning + "(" + startTime + "-12:00)");
                hourTime.add(noon + "(12:00-" + endTime + ")");
            } else {
                hourTime.add(morning + "(" + startTime + "-" + endTime + ")");
            }
        } else if (startHour >= TWELVE && startHour < EIGHTEEN) {
            if (endHour > EIGHTEEN) {
                hourTime.add(noon + "(" + startTime + "-18:00)");
                hourTime.add(night + "(18:00-" + endTime + ")");
            } else if (endHour == EIGHTEEN) {
                hourTime.add(noon + "(" + startTime + "-18:00)");
                String minute = endTime.split(":")[1];
                if(!Objects.equals(minute,secondSuf)){
                    hourTime.add(night + "(18:00-" + endTime + ")");
                }
            } else {
                hourTime.add(night + "(" + startTime + "-" + endTime + ")");
            }
        } else if (startHour >= EIGHTEEN) {
            hourTime.add(night + "(" + startTime + "-" + endTime + ")");
        }
        return hourTime;
    }

    private List<String> getBusinessByHour(int startHour, int endHour, int startMinute, int endMinute) {
        String startMinuteStr = "";
        String endMinuteStr = "";
        if (startMinute < TEN) {
            startMinuteStr = "0" + startMinute;
        } else {
            startMinuteStr = startMinuteStr + startMinute;
        }
        if (endMinute < TEN) {
            endMinuteStr = "0" + endMinute;
        } else {
            endMinuteStr = endMinuteStr + endMinute;
        }

        List<String> hourTime = Lists.newArrayList();
        int hour = startHour;
        if (startHour == endHour) {
            hourTime.add(startHour + ":" + startMinuteStr + "-" + endHour + ":" + endMinuteStr);
        }
        if (startMinute > 0) {
            hourTime.add(startHour + ":" + startMinuteStr + "-" + ++hour + ":00");
        }
        while (hour < endHour) {
            hourTime.add(hour + ":00-" + ++hour + ":00");
        }
        if (endMinute > 0) {
            hourTime.add(hour + ":00-" + hour + ":" + endMinuteStr);
        }
        return hourTime;
    }

    private List<String> getBusinessByHalfHour(int startHour, int endHour, int startMinute, int endMinute) {
        String startMinuteStr = "";
        String endMinuteStr = "";
        if (startMinute < TEN) {
            startMinuteStr = "0" + startMinute;
        } else {
            startMinuteStr = startMinuteStr + startMinute;
        }
        if (endMinute < TEN) {
            endMinuteStr = "0" + endMinute;
        } else {
            endMinuteStr = endMinuteStr + endMinute;
        }

        List<String> hourTime = Lists.newArrayList();
        int hour = startHour;
        if (startHour == endHour && startMinute < endMinute) {
            boolean flag = startMinute < THIRTY && endMinute <= THIRTY;
            if((startMinute >= THIRTY) || flag){
                hourTime.add(startHour + ":" + startMinuteStr + "-" + endHour + ":" + endMinuteStr);
            } else {
                hourTime.add(startHour + ":" + startMinuteStr + "-" + endHour + ":30");
                hourTime.add(startHour + ":30" + "-" + endHour + ":" + endMinute);
            }
            return hourTime;
        }
        if (startMinute > 0 && startMinute < THIRTY) {
            hourTime.add(startHour + ":" + startMinuteStr + "-" + hour + ":30");
            hourTime.add(startHour + ":30-" + ++hour + ":00");
        } else if (startMinute >= THIRTY) {
            hourTime.add(startHour + ":" + startMinute + "-" + ++hour + ":00");
        }
        while (hour < endHour) {
            hourTime.add(hour + ":00-" + hour + ":30");
            hourTime.add(hour + ":30-" + ++hour + ":00");
        }
        if (endMinute > 0 && endMinute < THIRTY) {
            hourTime.add(hour + ":00-" + hour + ":" + endMinuteStr);
        } else if (endMinute >= THIRTY) {
            hourTime.add(hour + ":00-" + hour + ":30");
            hourTime.add(hour + ":30-" + hour + ":" + endMinuteStr);
        }
        return hourTime;
    }

    @Override
    @Cacheable(cacheNames = "station", key = "#stationId")
    public StationVO getStationInfoById(Long stationId) {
        StationVO stationInfoById = stationMapper.getByStationId(stationId);
        return stationInfoById;
    }

    @Override
    public Double getStationDistance(Long stationId, Double lat, Double lng) {
        return stationMapper.getStationDistance(stationId, lat, lng);
    }
}
